package gui;

import javax.swing.DefaultListModel;
import javax.swing.JPanel;

import evolutionaryLoop.EvolutionaryParameters;
import evolutionaryProblems.Phenotype;
import evolutionaryProblems.RunPhenotype;

public abstract class GameModel<T extends RunPhenotype> {
	
	protected T runPhenotype; 
	protected GamePanel gamePanel; 
	private long timePerFrame = 200; 
	private DefaultListModel<Phenotype> listModel = new DefaultListModel<Phenotype>();
	private GUIFrame guiFrame;
	protected RunSettingPanel runSettingPanel; 
	
	public GameModel(GUIFrame guiFrame){
		this.guiFrame = guiFrame; 
		gamePanel = new GamePanel(); 
		initPhenotypeList(); 
		initRunPanel(); 
	}

	protected void initPhenotypeList(){
		JPanel listPanel = new PhenotypeList(this, listModel);
		gamePanel.setPhenotypeListPanel(listPanel); 
	}

	protected void initRunPanel() {
		runSettingPanel = new RunSettingPanel(this); 
		gamePanel.setGameSettingsPanel(runSettingPanel); 
	}
	
	public void runSelectedPhenotype(int index){
		runSettingPanel.unPause();
		try {
			runPhenotype(listModel.get(index));
		} catch (ArrayIndexOutOfBoundsException e) {
//			e.printStackTrace();
		} 
	}
	
	protected abstract void runPhenotype(Phenotype phenotype); 
	
	public long getTimePerFrame() {
		return timePerFrame;
	}
	
	public void setTimePerFrame(long timePerFrame){
		this.timePerFrame = timePerFrame;
	}
	
	public abstract int getIterationsPerMap();
	
	public void setMap(JPanel mapthing){
		gamePanel.setRunGamePanel(mapthing); 
	}
	
	public void addPheontype(Phenotype phenotype, int generation){
		if (listModel.contains(phenotype)){
			return; 
		}
		listModel.addElement(phenotype.getListClone(generation)); 
	}

	public JPanel getGamePanel(){
		return gamePanel; 
	}

	public void pack() {
		guiFrame.pack(); 
	}

	public void reset(){
		if (runPhenotype == null) {
			return; 
		}
		runPhenotype.kill(); 
		while (!runPhenotype.haveKilled()) {
			try {
				Thread.sleep(20);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public void pauseSimulation() {
		if (runPhenotype == null) {
			return; 
		}
		runPhenotype.pause(true);
	}

	public void continueSimulation() {
		if (runPhenotype == null) {
			return; 
		}
		runPhenotype.pause(false);
	}
	
	public void resetPhenoypeList() {
		listModel.removeAllElements(); 
	}

}
